home *** CD-ROM | disk | FTP | other *** search
- /*
- TCPNameToAddr(hostName,timeOut,hostFile) -- Return a list of alternative addresses for the host
- name specified. If the name can't be resolved locally, go ask a name server. If it can't be resolved
- within timeOut ticks, give up. The hostFile parameter gives the file name of a local name table
- file. The last two parameters are optional. timeOut defaults to 1800. hostFile defaults to none.
-
- To compile and link this file using Macintosh Programmer's Workshop,
-
- c -b TCPNameToAddr.p
- link -m ENTRYPOINT -o "TCP XCMD Example" -rt XFCN=7870 -sn Main=TCPNameToAddr ∂
- TCPNameToAddr.c.o "{Libraries}HyperXLib.o" "{Libraries}Interface.o" "{CLibraries}CInterface.o" ∂
- "{CLibraries}StdCLib.o"
-
- © Copyright 1989 by Apple Computer, Inc.
-
- Initial coding 3/89 by Harry R. Chesley.
- */
-
- #include <OSUtils.h>
- #include <Errors.h>
- #include <Files.h>
- #include <Resources.h>
- #include <Memory.h>
- #include <Events.h>
- #include <HyperXCmd.h>
- #include <String.h>
- #include "MacTCPCommonTypes.h"
-
- /* DNR resource function IDs. */
- #define OPENRESOLVER 1
- #define CLOSERESOLVER 2
- #define STRTOADDR 3
- #define ADDRTOSTR 4
- #define ENUMCACHE 5
- #define ADDRTONAME 6
-
- /* Default time-out. */
- #define DEFAULTTICK 3600
- /* Minimum time-out (to fix bug in MacTCP). */
- #define MINTICK 2400
-
- /* Number of addresses returned by DNR. */
- #define NUM_ALT_ADDRS 4
-
- /* DNR return structure. */
- typedef struct hostInfo {
- int rtnCode; /* Result code. */
- char cname[255]; /* Standard name. */
- unsigned long addr[NUM_ALT_ADDRS]; /* Addresses. */
- };
-
- typedef OSErr (*OSErrProcPtr)();
-
- pascal void EntryPoint(XCmdPtr paramPtr)
-
- {
- Handle codeHndl; /* DNR code resource handle. */
- OSErrProcPtr dnr; /* Pointer to code resource. */
- SysEnvRec info; /* System info record (to find the system volume). */
- HParamBlockRec fi; /* Parameter block (to find the MacTCP file). */
- Str255 filename; /* File name (for MacTCP file search). */
- char str[256]; /* Scratch string. */
- char resultStr[256]; /* Result string. */
- Handle resultHand; /* Result handle. */
- short refnum; /* Resource file refnum. */
- OSErr rc; /* Result code return. */
- struct hostInfo rtnStruct; /* Answer from DNR. */
- struct hostInfo cacheFltRtn; /* Place to return the answer if there's a cache fault. */
- long lastTick; /* When to time-out. */
- int i;
- pascal void resultProc();
- void errAbort();
-
- /* Check that we've got the right number of parameters. */
- if ((paramPtr->paramCount < 1) || (paramPtr->paramCount > 3)) {
- errAbort(paramPtr,"§§§ parameter count must be 1, 2, or 3 §§§");
- return;
- };
-
- /* Get the system volume. */
- SysEnvirons(1, &info);
-
- /* Prepare to scan for the MacTCP file (where we'll find the DNR code resource). */
- fi.fileParam.ioCompletion = nil;
- fi.fileParam.ioNamePtr = &filename;
- fi.fileParam.ioVRefNum = info.sysVRefNum;
- fi.fileParam.ioDirID = 0;
- fi.fileParam.ioFDirIndex = 1;
- refnum = -1;
- /* Scan for MacTCP file. */
- while (PBHGetFInfo(&fi, false) == noErr) {
- /* scan system folder for driver resource files of specific type & creator */
- if (fi.fileParam.ioFlFndrInfo.fdType == 'cdev' &&
- fi.fileParam.ioFlFndrInfo.fdCreator == 'mtcp') {
- /* Found the MacTCP driver file. */
- SetVol(nil,fi.fileParam.ioVRefNum);
- refnum = OpenResFile(&filename);
- break;
- };
- /* Check next file in system folder. */
- fi.fileParam.ioFDirIndex++;
- fi.fileParam.ioDirID = 0;
- };
-
- /* Ignore failures since the resource may have been installed in the
- System file if running on a Mac 512Ke. */
-
- /* Load in the DNR resource package. */
- codeHndl = GetIndResource('dnrp', 1);
- if (codeHndl == nil) {
- if (refnum != -1) CloseResFile(refnum);
- errAbort(paramPtr,"§§§ couldn't open resource §§§");
- return;
- };
- DetachResource(codeHndl);
- if (refnum != -1) CloseResFile(refnum);
-
- /* Lock the DNR resource so it cannot be relocated while opened. */
- HLock(codeHndl);
- dnr = (OSErrProcPtr) *codeHndl;
-
- /* Call open resolver. */
- if ((paramPtr->paramCount < 3) || (paramPtr->params[2] == nil)) *str = 0;
- else strcpy(str,*(paramPtr->params[2]));
- rc = (*dnr)(OPENRESOLVER, str);
- if (rc != noErr) {
- /* Problem with open resolver, flush it. */
- HUnlock(codeHndl);
- DisposHandle(codeHndl);
- errAbort(paramPtr,"§§§ domain name resolver failed §§§");
- return;
- };
-
- /* Get the address. */
- if (paramPtr->params[0] == nil) *str = 0;
- else strcpy(str,*(paramPtr->params[0]));
- cacheFltRtn.rtnCode = 1;
- rc = (*dnr)(STRTOADDR, str, &rtnStruct, resultProc, &cacheFltRtn);
-
- /* If we couldn't get it right away, wait for it. */
- if (rc == cacheFault) {
- if ((paramPtr->paramCount < 2) || (paramPtr->params[1] == nil)) lastTick = TickCount() + DEFAULTTICK;
- else if (**paramPtr->params[1] == 0) lastTick = TickCount() + DEFAULTTICK;
- else {
- ZeroToPas(paramPtr,*(paramPtr->params[1]),str);
- if ((lastTick = StrToNum(paramPtr,str)) > MINTICK) lastTick = MINTICK;
- lastTick = lastTick + TickCount();
- };
- while ((TickCount() < lastTick) && (cacheFltRtn.rtnCode > 0));
- rtnStruct = cacheFltRtn;
- } else rtnStruct.rtnCode = rc;
-
- /* Check if we got it OK or not. */
- if (rtnStruct.rtnCode == noErr) {
- /* We did, so build the result string. */
- *resultStr = 0;
- for (i = 0; i < NUM_ALT_ADDRS; i++) {
- if (rtnStruct.addr[i] == 0) break;
- if (i > 0) strcat(resultStr,",");
- NumToStr(paramPtr,rtnStruct.addr[i],str);
- p2cstr(str);
- strcat(resultStr,str);
- };
- /* Make the handle to return. */
- resultHand = NewHandle((long) strlen(resultStr)+1);
- if (resultHand != nil) {
- strcpy(*resultHand,resultStr);
- paramPtr->returnValue = resultHand;
- } else errAbort(paramPtr,"§§§ couldn't make result string §§§");
- } else if (rtnStruct.rtnCode == 1) errAbort("§§§ time-out §§§");
- else errAbort(paramPtr,"§§§ couldn't get address §§§");
-
- /* Call close resolver. */
- (void) (*dnr)(CLOSERESOLVER);
-
- /* Release the DNR resource package. */
- HUnlock(codeHndl);
- DisposHandle(codeHndl);
- }
-
- /* Async routine called when name is found from name server. We just copy the result
- and let the main loop process it. */
-
- pascal void resultProc(struct hostInfo *hostInfoPtr, struct hostInfo *userDataPtr)
-
- {
- *userDataPtr = *hostInfoPtr;
- }
-
- /* Error handling: return the string as a result. */
-
- void errAbort(XCmdPtr paramPtr, char *str)
-
- {
- Handle nuHndl;
-
- /* Allocate space for an error message, copy the string into it, and return the handle to HyperCard. */
- nuHndl = NewHandle((long)(strlen(str)+1));
- if (nuHndl == nil) return;
- strcpy((char *)*nuHndl,str);
- paramPtr->returnValue = nuHndl;
- }
-